// Copyright (c) 2002-2003, Sony Computer Entertainment America
// Copyright (c) 2002-2003, Craig Reynolds <craig_reynolds@playstation.sony.com>
// Copyright (C) 2007 Bjoern Graf <bjoern.graf@gmx.net>
// Copyright (C) 2007 Michael Coles <michael@digini.com>
// All rights reserved.
//
// This software is licensed as described in the file license.txt, which
// you should have received as part of this distribution. The terms
// are also available at http://www.codeplex.com/SharpSteer/Project/License.aspx.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;

namespace Bnoerj.AI.Steering.Pedestrian
{
	using ProximityDatabase = IProximityDatabase<IVehicle>;
	using ProximityToken = ITokenForProximityDatabase<IVehicle>;
    using PloobsEngine.SceneControl;
    using PloobsEngine;
    using Etapa1.Pedestrian;
    using PloobsEngine.Material;
    using PloobsEngine.Physics.Bepu;
    using PloobsEngine.Modelo;
    using PloobsEngine.Draw;
    
	public class SteerPathPlugIn : PlugIn
	{
        IWorld world;        
        EngineStuff engine;        

        public SteerPathPlugIn(IWorld world, EngineStuff engine)
			: base()
		{            
			crowd = new List<SteerPathFinderVehicle>();
            this.world = world;
            this.engine = engine;
		}

		public override String Name { get { return "Pedestrians"; } }

		public override float SelectionOrderSortKey { get { return 0.02f; } }

		public override void Open()
		{
			// make the database used to accelerate proximity queries
			cyclePD = -1;
			NextPD();

			// create the specified number of Pedestrians
			population = 0;
			//for (int i = 0; i < 10; i++) AddPedestrianToCrowd();
			
		}

		public override void Update(float currentTime, float elapsedTime)
		{
			// update each Pedestrian
			for (int i = 0; i < crowd.Count; i++)
			{                
				crowd[i].Update(currentTime, elapsedTime);
			}
		}

		public override void Redraw(float currentTime, float elapsedTime)
		{            
            
		}
	
	
		public override void Close()
		{
			// delete all Pedestrians
			//while (population > 0) RemovePedestrianFromCrowd();
		}

		public override void Reset()
		{
			// reset each Pedestrian
			//for (int i = 0; i < crowd.Count; i++) crowd[i].Reset();			
		}

		public override void HandleFunctionKeys(Keys key)
		{			
		}

		public override void PrintMiniHelpForFunctionKeys()
		{
#if TODO
			std::ostringstream message;
			message << "Function keys handled by ";
			message << '"' << name() << '"' << ':' << std::ends;
			Demo.printMessage (message);
			Demo.printMessage (message);
			Demo.printMessage ("  F1     add a pedestrian to the crowd.");
			Demo.printMessage ("  F2     remove a pedestrian from crowd.");
			Demo.printMessage ("  F3     use next proximity database.");
			Demo.printMessage ("  F4     toggle directed path follow.");
			Demo.printMessage ("  F5     toggle wander component on/off.");
			Demo.printMessage ("");
#endif
		}

		public void AddAgente(PolylinePathway path, List<SphericalObstacle> obstacles)
		{
			population++;
            SteerPathFinderVehicle pedestrian = new SteerPathFinderVehicle(pd,path,obstacles );
            pedestrian.Reset();

            SimpleModel sm = new SimpleModel("..\\Content\\Model\\block", "..\\Content\\Textures\\caixaTex");
            sm.LoadModelo();
            BoxObject pi = new BoxObject(new Vector3(0, 10, 100), 1,new Vector3(3));
            ObjectMover om = new ObjectMover(pi);
            
            IShader shader = new NormalDeferred();
            shader.Initialize();
            IMaterial mat = new Material(shader, MaterialType.DEFERRED);                                    
            SteerObject agent = new SteerObject(pedestrian, mat, pi, sm);
            world.AddObject(agent);
			crowd.Add(pedestrian);
            pi.Position = pedestrian.Position;
		}

		void RemovePedestrianFromCrowd()
		{            
		}

		// for purposes of demonstration, allow cycling through various
		// types of proximity databases.  this routine is called when the
		// OpenSteerDemo user pushes a function key.
		void NextPD()
		{
			// save pointer to old PD
			ProximityDatabase oldPD = pd;

			// allocate new PD
			const int totalPD = 2;
			switch (cyclePD = (cyclePD + 1) % totalPD)
			{
			case 0:
				{
					Vector3 center = Vector3.Zero;
					float div = 20.0f;
					Vector3 divisions = new Vector3(div, 1.0f, div);
					float diameter = 80.0f; //XXX need better way to get this
					Vector3 dimensions = new Vector3(diameter, diameter, diameter);
					pd = new LocalityQueryProximityDatabase<IVehicle>(center, dimensions, divisions);
					break;
				}
			case 1:
				{
					pd = new BruteForceProximityDatabase<IVehicle>();
					break;
				}
			}

			// switch each boid to new PD
			for (int i = 0; i < crowd.Count; i++) crowd[i].NewPD(pd);

			// delete old PD (if any)
			oldPD = null;
		}

		public override List<IVehicle> Vehicles
		{
            get { return crowd.ConvertAll<IVehicle>(delegate(SteerPathFinderVehicle p) { return (IVehicle)p; }); }
		}

        List<SteerPathFinderVehicle> crowd;

		// pointer to database used to accelerate proximity queries
		ProximityDatabase pd;

		// keep track of current flock size
		int population;

		// which of the various proximity databases is currently in use
		int cyclePD;
	}
}
